package simpleTaskDispatcher.model.taskDispatchers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Logger;

import simpleTaskDispatcher.model.DispatchingChange;
import simpleTaskDispatcher.model.TaskQueue;
import simpleTaskDispatcher.model.enums.DispatchingEvent;

public abstract class AbstractTaskQueueDispatcher implements ITaskQueueDispatcher {

	private int taskQueuesLimit = -1;

	private Comparator<TaskQueue> comparator;

	public AbstractTaskQueueDispatcher(int taskQueuesLimit,
			Comparator<TaskQueue> comparator) {
		super();
		this.taskQueuesLimit = taskQueuesLimit;
		this.comparator = comparator;
	}

	public AbstractTaskQueueDispatcher(int taskQueuesLimit) {
		super();
		this.taskQueuesLimit = taskQueuesLimit;
		this.comparator = TaskQueueComparators.compareByAscCreation();
	}

	public AbstractTaskQueueDispatcher(Comparator<TaskQueue> comparator) {
		super();
		this.comparator = comparator;
	}

	@Override
	public void dispatch(List<DispatchingChange> changes,
			DispatchingEvent event, List<TaskQueue> taskQueues, int freeWorkers,
			int plannedFreeWorkers, Object eventParameter) {

		List<TaskQueue> sortedTaskQueues = new ArrayList<TaskQueue>();
		sortedTaskQueues.addAll(taskQueues);
		Collections.sort(sortedTaskQueues, comparator);

		if (taskQueuesLimit != -1) {
			while (sortedTaskQueues.size() > taskQueuesLimit) {
				TaskQueue queue = sortedTaskQueues.remove(taskQueuesLimit);
				if (queue.getPlannedNbWorkers() > 0) {
					changes.add(DispatchingChange.release(queue,
							queue.getPlannedNbWorkers()));
				}
			}
		}

		Logger.getLogger(getClass().getSimpleName() + ": Dispatching because of "
				+ event.name()
				+ ". Task queues : "
				+ taskQueues.size()
				+ ", workers : " + plannedFreeWorkers);

		dispatchSorted(changes, event, sortedTaskQueues, freeWorkers,
				plannedFreeWorkers, eventParameter);
		
		for(DispatchingChange change : changes) {
			Logger.getLogger(getClass().getSimpleName() + " : " + change.toString());
		}
	}

	protected abstract void dispatchSorted(List<DispatchingChange> changes,
			DispatchingEvent event, List<TaskQueue> taskQueues, int freeWorkers,
			int plannedFreeWorkers, Object eventParameter);

}
